//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#if _MSC_VER > 1000
#pragma once
#endif

#ifndef __CKPROCESS_H_
#define __CKPROCESS_H_

#include <elasys_server.h>
#include <linknode.h>
#include <interlocked.h>
#include "cthread.h"
#include "cmodule.h"
#include <aura.h>

class _CMemoryTrace : public IMemoryTrace
{
public:
    CARAPI_(PInterface) Probe(REIID riid);

};

class CProcess : public DLinkNode, public IProcess
{
// Interface functions
//
public:
    CARAPI_(PInterface) Probe(
        /* [in]  */ REIID riid);

    CARAPI_(UInt32) AddRef(void);

    CARAPI_(UInt32) Release(void);

    CARAPI Aggregate(
        /* [in] */ AggregateType type,
        /* [in] */ PInterface pObject);

    CARAPI GetDomain(
        /* [out] */ PInterface *ppObject);

    CARAPI Start(
        /* [in] */ WString wsName,
        /* [in] */ WString wsArgs);

    CARAPI Kill();

    CARAPI WaitForExit(
        /* [in] */ Millisecond32 timeout,
        /* [out] */ WaitResult *pResult);

    CARAPI IsAlive(
        /* [out] */ Boolean *pAlive);

    CARAPI SetPriorityRank(
        /* [in] */ ThreadPriorityRank priorityRank);

    CARAPI GetPriorityRank(
        /* [out] */ ThreadPriorityRank * pPriorityRank);

    CARAPI SetThreadPoolCapacity(
        /* [in] */ Int32 capacity);

    CARAPI GetThreadPoolState(
        /* [out] */ Int32 * pCapacity,
        /* [out] */ Int32 * pThreads);

    CARAPI GetAllThreads(
        /* [out] */ IObjectEnumerator ** ppThreads);

    CARAPI GetAllModules(
        /* [out] */ IObjectEnumerator ** ppModules);

    CARAPI GetModuleByName(
        /* [in] */ WString name,
        /* [out] */ IModule * * ppModule);

    CARAPI GetModuleByAddress(
        /* [in] */ Address address,
        /* [out] */ IModule * * ppModule);

    CARAPI GetId(
        /* [out] */ ProcessId * pPid);

    CARAPI GetStartInfo(
        /* [out] */ WStringBuf * pName,
        /* [out] */ WStringBuf * pArgs);

    CARAPI GetExitCode(
        /* [out] */ ExitCode * pExitCode);

    CARAPI GetStartTime(
        /* [out] */ SystemTime * pTime);

    CARAPI GetExitTime(
        /* [out] */ SystemTime * pTime);

    CARAPI GetProcessorTimes(
        /* [out] */ Millisecond32 * pUserTime,
        /* [out] */ Millisecond32 * pKernelTime);

    CARAPI GetMemorySizes(
        /* [out] */ MemorySize * pPrivateVirtualMemorySize,
        /* [out] */ MemorySize * pSharedVirtualMemorySize,
        /* [out] */ MemorySize * pPrivatePhysicalMemorySize,
        /* [out] */ MemorySize * pSharedPhysicalMemorySize);

    // IMemoryTrace
    CARAPI SetTraceArgs(
        /* [in] */ Int32 argId,
        /* [in] */ Int32  index,
        /* [in] */ Address watchAddress);

    CARAPI SetTraceDebug(
        /* [in] */ Boolean debug);

    CARAPI IsTraceDebug(
        /* [out] */ Boolean *pDebug);

public: // not CAR interface for IThread.

    CARAPI AcquireThreadLocalSlot(
        /* [in] */ ThreadLocalSlotType type,
        /* [out] */ Int32 *pSlotIndex);

    CARAPI RelinquishThreadLocalSlot(
        /* [in] */ Int32 slotIndex,
        /* [out] */ BufferOf<Address> * pUsedPtrs);

    CARAPI CleanUpThreadLocalSlot(
        /* [in] */ Int32 slotIndex,
        /* [out] */ BufferOf<Address> * pUsedPtrs);

    CARAPI GetThreadLocalSlotValue(
        /* [in] */ ThreadLocalSlotType type,
        /* [in] */ Int32 slotIndex,
        /* [out] */ PVoid * ppValue);

    CARAPI SetThreadLocalSlotValue(
        /* [in] */ ThreadLocalSlotType type,
        /* [in] */ Int32 slotIndex,
        /* [in] */ PVoid pValue);

public: // static member functions.
    STATIC ECode S_Create(
        /* [out] */ IProcess ** ppProcess,
        /* [out] */ IThread  ** ppMainThread);

public:
    void AttachThread(CThread * pThread);
    void DetachThread(CThread * pThread);
    void DetachModule(CModule * pModule);

    void DoAtExit(ExitCode nexitCode);
    ECode LoadModule(
        /* [in] */ WString name,
        /* [in] */ ModuleLoadFlags flags,
        /* [out] */ IModule ** ppModule);

    ECode RequestSystemEvent(
        /* [in] */ SystemEvents interestedEvents,
        /* [out] */ IEvent **ppEvent);

public:
    CProcess();
    virtual ~CProcess();
    ECode Initialize();
    ECode TrySetStartInfo();

private:
    ECode ModulesInitialize();

public:
    WStringBuf_<MAXIMUM_FULL_PATH_LENGTH> m_name;
    WStringBuf_<MAXIMUM_ARGS_LENGTH>      m_args;

    ProcessId   m_processId;
    Aura_Handle m_hProcess;
    IThread   * m_pMainThread;

    DLinkNode   m_threadList;       // thread object list.
    Int32       m_threadListState;
    PVoid       m_hThreadListLock;

    DLinkNode   m_moduleList;       // module object list.
    Int32       m_moduleListState;
    PVoid       m_hModuleListLock;

    ExitCode    m_exitCode;
    Int32       m_threadPoolCapacity;

    PVoid       m_hTlsLock;
    Byte        m_tlsSlotType[TLS_TOTAL_SLOTS];

private:
    Interlocked m_Refs;
};

#endif
